図解「generator・native coroutine・with」 〜 関心やコードを分離する文法と、処理順序・構造
コルーチン・native coroutineという言葉にまつわるPythonの"混乱"の整理
native coroutineとは、async / await
async / await (native coroutine) はコルーチンの性質を全てを持たないが native coroutineと呼ばれている(これが混乱)
頻繁に用いる決まった手続き:ルーチン として記述する事で、再利用しやすくできます。
Pythonを含む多くのプログラミング言語では、関数をルーチンの定義に用いることもできます。
関数の中でさらに別の関数を呼び出すという、関数の呼び出しの連続によってプログラミングは行われている、 と言っても過言ではありません。
main()を実行するときには、途中でsub_routine()が呼ばれますが、sub_routine()が呼ばれてからはその処理を一通り実行して戻ってくる、というような流れになっています。
コルーチンは、プログラミング言語全般における用語です。単純な関数呼び出しによるサブルーチンとは異なり、呼び出し元と呼び出し先を行ったり来たりするような関係性のルーチンを指します。
コルーチンのコとは、コラボのコと同じで、「共に」というようなニュアンスの接頭語です。
Pythonで、一般的なコルーチンを実現するには、generatorというものを用います。文法的には、yieldというものをreturnの代わりに書くだけです。
native coroutine(Pythonでいうcoroutine)・async/await
Pythonではnative coroutineというものを用意しています。
これは、先程のカタカナのコルーチンとはまた違う意味を持っている
asyncの付いている関数定義は、generatorと同じように、呼び出しをしても直ちに実行はされない関数になります。
generatorの場合はsend()を都度実行するのでしたが、native coroutineの場合はasyncio.run()やasyncio.gather()などによって実行します。
実は、await asyncio.gather()をすると、その引数のnative coroutine達の処理が終了するか、またはタイムアウトするまで待ち続けてしまう ので、コルーチンにおける行ったり来たりという処理ができないのです。
ですが、Pythonではこれを(native) coroutineと呼んでいます。(※強調は引用者による)
JavaScript界隈(やUnity界隈など)で「非同期の処理を含む特殊なコルーチン」の事を、単に「コルーチン」と呼ぶ事があり、それに引きずられた形になっています。
Pythonの仕様PEP492に落とし込んだ時にcoroutineと呼ぶことになってしまったのでした。
実は、これを行ったり来たりできるようにした async generator というものも存在していて、それはPEP525でPEP492と同じ方が提案して実際に使えるようになっています